package com.ruoyi.finance.utils;

import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.finance.domain.SearchRentInstallmentDetailMiniResponseDTO;
import com.ruoyi.finance.domain.SearchRentInstallmentDetailResponseDTO;
import com.ruoyi.finance.domain.request.SearchRentInstallmentDetailRequestDTO;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 
 * @Title: 通用方法 - 金融
 * @Description: TODO
 * @author zhangxurui
 * @date 2018年5月14日 下午8:56:20
 */
public class MyJinRongUtils {

	/**
	 * 根据一段时间区间，按月份拆分成多个时间段
	 * 
	 * @param startDate
	 *            开始日期
	 * @param endDate
	 *            结束日期
	 * @return
	 */
	public static List<KeyValueForDate> getSplitMonthForDate(Date start, Date end) {
		String startDate = new SimpleDateFormat("yyyy-MM-dd").format(start);
		String endDate = new SimpleDateFormat("yyyy-MM-dd").format(end);
		List<KeyValueForDate> list = null;
		try {
			list = new ArrayList<KeyValueForDate>();
			Date d1 = new SimpleDateFormat("yyyy-MM-dd").parse(startDate);// 定义起始日期
			Date d2 = new SimpleDateFormat("yyyy-MM-dd").parse(endDate);// 定义结束日期
			Calendar dd = Calendar.getInstance();// 定义日期实例
			dd.setTime(d1);// 设置日期起始时间
			Calendar c = Calendar.getInstance();
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
			KeyValueForDate keyValueForDate = null;
			while (dd.getTime().before(d2)) {// 判断是否小于结束日期
				if (sdf.format(dd.getTime()).equals(sdf.format(d1))) {
					keyValueForDate = new KeyValueForDate();
					keyValueForDate.setStartDate(sdf.format(dd.getTime()));
					c.setTime(dd.getTime());
					c.add(Calendar.MONTH, 1);
					c.add(Calendar.DATE, -1);
					keyValueForDate.setEndDate(sdf.format(c.getTime()));
					list.add(keyValueForDate);
					dd.setTime(c.getTime());
				} else {
					c.setTime(dd.getTime());
					c.add(Calendar.DATE, 1);
					dd.setTime(c.getTime());
					keyValueForDate = new KeyValueForDate();
					keyValueForDate.setStartDate(sdf.format(dd.getTime()));
					c.setTime(dd.getTime());
					c.add(Calendar.MONTH, 1);
					SimpleDateFormat mm = new SimpleDateFormat("MM");
					SimpleDateFormat yy = new SimpleDateFormat("yyyy");
					int year = Integer.parseInt(yy.format(c.getTime()));
					if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
						if (mm.format(c.getTime()).equals("02")) {
						}
					} else {
						if (mm.format(c.getTime()).equals("02")) {
							c.add(Calendar.DATE, 1);
						}
					}
					String checkd1 = sdf.format(c.getTime());
					String checkd2 = sdf.format(d2.getTime());
					if (d2.before(c.getTime()) || checkd1.equals(checkd2)) { // 判断是否大于结束日期，是则直接保存结束日期
						keyValueForDate.setEndDate(sdf.format(d2.getTime()));
						list.add(keyValueForDate);
						dd.setTime(c.getTime());
					} else {// 保存结束日期
						c.add(Calendar.DATE, -1);
						keyValueForDate.setEndDate(sdf.format(c.getTime()));
						list.add(keyValueForDate);
						dd.setTime(c.getTime());
					}
				}
			}
		} catch (ParseException e) {
			return null;
		}
		return list;
	}

	/**
	 * 
	 * @Description: 进行加法运算
	 * @param d1
	 * @param d2
	 * @return double
	 */
	public static double add(double d1, double d2) { //
		BigDecimal b1 = new BigDecimal(d1);
		BigDecimal b2 = new BigDecimal(d2);
		return b1.add(b2).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
	}

	/**
	 * 
	 * @Description: 进行减法运算
	 * @param d1
	 * @param d2
	 * @return double
	 */
	public static double sub(double d1, double d2) {
		BigDecimal b1 = new BigDecimal(d1);
		BigDecimal b2 = new BigDecimal(d2);
		return b1.subtract(b2).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
	}

	/**
	 * 
	 * @Description: 进行乘法运算
	 * @param d1
	 * @param d2
	 * @return double
	 */
	public static double mul(double d1, double d2) {
		BigDecimal b1 = new BigDecimal(d1);
		BigDecimal b2 = new BigDecimal(d2);
		return b1.multiply(b2).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
	}

	/**
	 * 
	 * @Description: 进行除法运算
	 * @param d1
	 * @param d2
	 * @param len
	 * @return double
	 */
	public static double div(double d1, double d2, int len) {
		BigDecimal b1 = new BigDecimal(d1);
		BigDecimal b2 = new BigDecimal(d2);
		return b1.divide(b2, len, BigDecimal.ROUND_HALF_UP).doubleValue();
	}

	/**
	 * 
	 * @Description: 计算 - 分期利率使用
	 * @param SearchRentInstallmentDetailRequestDTO
	 * @return SearchRentInstallmentDetailResponseDTO
	 * @throws ParseException
	 */
	public static SearchRentInstallmentDetailResponseDTO getComputeFQ(SearchRentInstallmentDetailRequestDTO dto)
			throws ParseException {
		// 每月租金 = （总金额 / 期数）
		// 每月利息 = 每月租金 * （一次性服务 + 利率）
		// 每月净值 = 每月租金 - 每月利息
		SearchRentInstallmentDetailResponseDTO res = new SearchRentInstallmentDetailResponseDTO();
		List<SearchRentInstallmentDetailMiniResponseDTO> arr = new ArrayList<>();
		SearchRentInstallmentDetailMiniResponseDTO detail;
		double rate = MyJinRongUtils.div(Double.parseDouble(dto.getRate()), 100, 2);// 利率
		double balance = dto.getBalance();// 余额
		double tenantRate = 0;
		double businessRate = 0;
		double serviceFee = 0;
		if (StringUtils.isNotBlank(dto.getTenantRate())) {
			tenantRate = MyJinRongUtils.div(Double.parseDouble(dto.getTenantRate()), 100, 2);// 租客承担比例
		}
		if (StringUtils.isNotBlank(dto.getBusinessRate())) {
			businessRate = MyJinRongUtils.div(Double.parseDouble(dto.getBusinessRate()), 100, 2);// 公寓承担比例
		}
		if (StringUtils.isNotBlank(dto.getServiceFee())) {
			serviceFee = MyJinRongUtils.div(Double.parseDouble(dto.getServiceFee()), 100, 2);// 一次性服务费
		}
		double creditLine = MyJinRongUtils.div(dto.getCreditLine(), 100, 2);// 授信额度 百分比
		List<KeyValueForDate> splitMonth = getSplitMonthForDate(dto.getStartDate(), dto.getEndDate());
		int periods = splitMonth.size(); // 期数
		double monthMonery = div(balance, periods, 2); // 月租金
		double inInterestCount = 0;// 利息合计
		double serviceFeeCount = 0; // 服务费合计
		int no = 1;
		for (KeyValueForDate v : splitMonth) {
			detail = new SearchRentInstallmentDetailMiniResponseDTO();
			detail.setNo(no);
			detail.setRealEstateInfo(dto.getRealEstateInfo());
			detail.setRoomCode(dto.getRoomCode());
			detail.setMonthlyRentReceivable(monthMonery);// 应收
			double rentEndInterest = MyJinRongUtils.getRentEndInterest(balance, tenantRate, creditLine);
			detail.setInstalmentInterest(rentEndInterest);// 分期后利息
			double rentEndMoney = MyJinRongUtils.add(monthMonery, rentEndInterest);
			detail.setMonthlyRentAfStag(rentEndMoney);// 分期后租金
			detail.setStarLoanday(v.getStartDate());
			detail.setEndLoanday(v.getEndDate());
			arr.add(detail);
			no++;
		}

		double reLeaseCount = MyJinRongUtils.mul(balance, creditLine);
		inInterestCount = MyJinRongUtils.getInterests(balance, businessRate, periods, creditLine);// 利息合计
		serviceFeeCount = MyJinRongUtils.getInterests(balance, serviceFee, periods, creditLine); // 服务费合计
		res.setReLeaseCount(reLeaseCount + "");// 应收租约合计（授信后）
		res.setInInterestCount(inInterestCount + "");// 公寓利息合计
		res.setSerCharge(serviceFeeCount + "");// 服务费合计
		res.setCoHirerentCount(MyJinRongUtils.getCoHirerent(reLeaseCount, inInterestCount, serviceFeeCount) + "");// 分期后租金合计
		res.setRentInstalDetail(arr);
		return res;
	}

	/**
	 * 
	 * @Description: 计算 - 利息
	 * @param monthMonery
	 * @param inInterestCount
	 * @param serviceFeeCount
	 * @return double 服务费总 = 总额 * (服务费、公寓、利率等) / 12 * 期数
	 */
	public static double getInterests(double balance, double interest, int periods, double creditLine) {
		double mul = MyJinRongUtils.mul(balance, interest);
		double div = MyJinRongUtils.div(mul, 12, 2);
		double mul2 = MyJinRongUtils.mul(div, periods);
		return MyJinRongUtils.mul(mul2, creditLine);
	}

	/**
	 * 
	 * @Description: 计算 - 分期后租金合计
	 * @param monthMonery
	 * @param inInterestCount
	 * @param serviceFeeCount
	 * @return double
	 */
	public static double getCoHirerent(double balance, double inInterestCount, double serviceFeeCount) {
		double sub = MyJinRongUtils.sub(balance, inInterestCount);
		return MyJinRongUtils.sub(sub, serviceFeeCount);
	}

	/**
	 * 
	 * @Description: 计算 - 利息
	 * @param monthMonery
	 * @param businessRate
	 * @param creditLine
	 * @return double
	 */
	public static double getRentEndInterest(double monthMonery, double tenantRate, double creditLine) {
		double mul = MyJinRongUtils.mul(monthMonery, tenantRate);
		double mul2 = MyJinRongUtils.mul(mul, creditLine);
		return MyJinRongUtils.div(mul2, 12, 2);
	}
	
	/**
	 * 
	 * @Description: 计算 - 利息总和 - 审核使用
	 * @param reLeaseCount
	 *            应收租约合计（授信后）
	 * @param rate
	 *            利息
	 * @return double
	 */
	public static double getInterestCount(double reLeaseCount, double rate) {
		double mul = MyJinRongUtils.mul(reLeaseCount, rate);
		double div = MyJinRongUtils.div(mul, 12, 2);
		return MyJinRongUtils.div(div, 100, 2);
	}

	public static class KeyValueForDate {
		private String startDate;
		private String endDate;

		public String getStartDate() {
			return startDate;
		}

		public void setStartDate(String startDate) {
			this.startDate = startDate;
		}

		public String getEndDate() {
			return endDate;
		}

		public void setEndDate(String endDate) {
			this.endDate = endDate;
		}
	}

}
